package com.test.demo02_rectangle;

import androidx.appcompat.app.AppCompatActivity;

import android.opengl.GLES20;
import android.opengl.GLSurfaceView;
import android.opengl.Matrix;
import android.os.Bundle;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

/**
 * 正方形就是两个三角形。4个点构成
 */
public class MainActivity extends AppCompatActivity {

    private final String TAG = "MainActivity";

    private GLSurfaceView glSurfaceView;

    private FloatBuffer mVertexFloatBuffer;

    private static final String VERTEX_SHADER_FILE = "rectangle_vertex_shader.glsl";
    private static final String FRAGMENT_SHADER_FILE = "rectangle_fragment_shader.glsl";
    private static final String A_POSITION = "aPosition";
    private static final String A_COLOR = "aColor";
    private static final String U_MATRIX = "uMatrix"; //添加矩阵

    //在数组中，一个顶点需要3个来描述其位置，需要3个偏移量
    private static final int COORDINATES_PER_VERTEX = 3;
    private static final int COORDINATES_PER_COLOR = 3;

    //每个Float,4个字节
    public static final int BYTES_PER_FLOAT = 4;

    //在数组中，描述一个顶点，总共的顶点需要的偏移量。这里因为只有位置顶点，所以和上面的值一样
    private static final int TOTAL_COMPONENT_COUNT = COORDINATES_PER_VERTEX + COORDINATES_PER_COLOR;
    //一个点需要的byte偏移量。
    private static final int STRIDE = TOTAL_COMPONENT_COUNT * BYTES_PER_FLOAT;

    //顶点的坐标系
    //    //正方形的点0
    private static float SQUARE_COLOR_COORDINATES[] = {
            //Order of coordinates: X, Y, Z, R,G,B,
            -0.5f, 0.5f, 0.0f, 1.f, 0f, 0f,  //  0.top left RED
            -0.5f, -0.5f, 0.0f, 0.f, 0f, 1f, //  1.bottom right Blue
            0.5f, -0.5f, 0.0f, 0.f, 1f, 0f,  //  2.bottom left GREEN
            0.5f, 0.5f, 0.0f, 0.f, 0f, 0f,   //  3.top right WHITE
    };

    //正方形的点1
//    private static float SQUARE_COLOR_COORDINATES[] = {
//            //Order of coordinates: X, Y, Z, R,G,B,
//            -0.5f, 0.5f, 0.0f, 1.f, 0f, 0f,  //  0.top left RED
//            -0.5f, -0.5f, 0.0f, 0.f, 0f, 1f, //  1.bottom right Blue
//            0.5f, 0.5f, 0.0f, 1f, 1f, 1f,   //  3.top right WHITE
//            0.5f, -0.5f, 0.0f, 0.f, 1f, 0f,  //  2.bottom left GREEN
//    };

    private static final int VERTEX_COUNT = SQUARE_COLOR_COORDINATES.length / TOTAL_COMPONENT_COUNT;
    //program的指针
    private int mProgramObjectId;
    //投影矩阵
    private float[] mProjectionMatrix = new float[16];
    private int uMatrix;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        glSurfaceView = findViewById(R.id.gl_surface_view);
        glSurfaceView.setEGLContextClientVersion(2);

        mVertexFloatBuffer = ByteBuffer
                .allocateDirect(SQUARE_COLOR_COORDINATES.length * BYTES_PER_FLOAT)
                .order(ByteOrder.nativeOrder())
                .asFloatBuffer()
                .put(SQUARE_COLOR_COORDINATES);
        mVertexFloatBuffer.position(0);

        glSurfaceView.setRenderer(new GLSurfaceView.Renderer() {
            @Override
            public void onSurfaceCreated(GL10 gl, EGLConfig config) {
                GLES20.glClearColor(0f, 0f, 0f, 0f);

                String vertexShaderCode = OpenGLUtil.readAssetShaderCode(MainActivity.this,
                        VERTEX_SHADER_FILE);
                String fragmentShaderCode = OpenGLUtil.readAssetShaderCode(MainActivity.this,
                        FRAGMENT_SHADER_FILE);

                int vertxShaderObjId = OpenGLUtil.compileShaderCode(GLES20.GL_VERTEX_SHADER, vertexShaderCode);
                int fragmentShaderObjId = OpenGLUtil.compileShaderCode(GLES20.GL_FRAGMENT_SHADER, fragmentShaderCode);

                mProgramObjectId = GLES20.glCreateProgram();
                GLES20.glAttachShader(mProgramObjectId, vertxShaderObjId);
                GLES20.glAttachShader(mProgramObjectId, fragmentShaderObjId);
                GLES20.glLinkProgram(mProgramObjectId);

                GLES20.glUseProgram(mProgramObjectId);

                int aPosition = GLES20.glGetAttribLocation(mProgramObjectId, A_POSITION);
                mVertexFloatBuffer.position(0);
                GLES20.glVertexAttribPointer(
                        aPosition, COORDINATES_PER_VERTEX,
                        GLES20.GL_FLOAT, false,
                        STRIDE, mVertexFloatBuffer);
                GLES20.glEnableVertexAttribArray(aPosition);

                int aColor = GLES20.glGetAttribLocation(mProgramObjectId, A_COLOR);
                mVertexFloatBuffer.position(COORDINATES_PER_VERTEX);
                GLES20.glVertexAttribPointer(
                        aColor, COORDINATES_PER_COLOR,
                        GLES20.GL_FLOAT, false,
                        STRIDE, mVertexFloatBuffer);
                GLES20.glEnableVertexAttribArray(aColor);

                uMatrix = GLES20.glGetUniformLocation(mProgramObjectId, U_MATRIX);
            }

            @Override
            public void onSurfaceChanged(GL10 gl, int width, int height) {
                //在窗口改变的时候调用
                GLES20.glViewport(0, 0, width, height);
                //主要还是长宽进行比例缩放
                float aspectRatio = width > height ?
                        (float) width / (float) height :
                        (float) height / (float) width;
                if (width > height) {
                    //横屏。需要设置的就是左右。
                    Matrix.orthoM(mProjectionMatrix, 0, -aspectRatio, aspectRatio, -1, 1f, -1.f, 1f);
                } else {
                    //竖屏。需要设置的就是上下
                    Matrix.orthoM(mProjectionMatrix, 0, -1, 1f, -aspectRatio, aspectRatio, -1.f, 1f);
                }
            }

            @Override
            public void onDrawFrame(GL10 gl) {
                //GLES20.glClear（）的唯一参数表示需要被清除的缓冲区。当前可写的颜色缓冲
                GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT);

                //传递给着色器
                GLES20.glUniformMatrix4fv(uMatrix, 1, false, mProjectionMatrix, 0);

                //绘制三角形.
                //draw arrays的几种方式 GL_TRIANGLES三角形 GL_TRIANGLE_STRIP三角形带的方式(开始的3个点描述一个三角形，后面每多一个点，多一个三角形) GL_TRIANGLE_FAN扇形(可以描述圆形)
//        GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, VERTEX_COUNT);
                //使用indexBuffer的方式
//        GLES20.glDrawElements(GLES20.GL_TRIANGLES, SQUARE_INDEX.length, GLES20.GL_UNSIGNED_SHORT, mIndexBuffer);
                //1.使用三角形带的方式
                GLES20.glDrawArrays(GLES20.GL_TRIANGLE_STRIP, 0, VERTEX_COUNT);
            }
        });
    }

}